package com.therandoms.rtgdroid.steps;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.codepond.wizardroid.WizardStep;
import org.codepond.wizardroid.persistence.ContextVariable;
import org.therandoms.textgen.TextGeneratorDictionary;
import org.therandoms.textgen.WordnikOptions;
import org.therandoms.textgen.WordnikOptions.WordnikSortBy;
import org.therandoms.textgen.WordnikOptions.WordnikSortOrder;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;

import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;
import com.therandoms.rtgdroid.R;
import com.therandoms.rtgdroid.background.WordnikLoaderAsyncTask;
import com.wordnik.client.model.WordObject;

import de.keyboardsurfer.android.widget.crouton.Crouton;

/**
 * Prompts the user for production categories to populate with random words from
 * Wordnik.
 * 
 * @author Logan Widick
 * @author Vinh Pham
 */
@SuppressLint("ClickableViewAccessibility")
public class WordnikLoadingStep extends WizardStep {

	protected static final String TAG = "WordnikLoadingStep";

	/**
	 * The grammar object itself
	 */
	@ContextVariable
	private TextGeneratorDictionary<String> grammar;

	@ContextVariable
	private ArrayList<WordnikOptions> optionsToLoad;

	/**
	 * The spinner for wordnik API categories.
	 */
	private Spinner wordnikCategoriesSpinner = null;

	/**
	 * The spinner for production categories in the grammar.
	 */
	private Spinner productionCategoriesSpinner = null;

	/**
	 * Stores the (production category, wordnik category) pairs.
	 */
	private DragSortListView selectedItemsListView = null;

	/**
	 * The nonprintable wordnik categories.
	 */
	private ArrayList<String> nonprintableCategories = null;

	/**
	 * The printable wordnik categories.
	 */
	private ArrayList<String> printableCategories = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setHasOptionsMenu(true);
	}

	/**
	 * Constructor.
	 */
	public WordnikLoadingStep() {
		super();
	}

	@Override
	public void onExit(final int exitCode) {
		Crouton.cancelAllCroutons();
		if (exitCode == WizardStep.EXIT_NEXT) {
			if (adapter.getCount() > 0) {
				notifyCompleted(false);

				// get the preferences
				SharedPreferences prefs = PreferenceManager
						.getDefaultSharedPreferences(getActivity());
				boolean enableBadWordsFiltering = prefs.getBoolean(
						"com.therandoms.rtgdroid.enable_bad_filtering", true);

				// apply the preferences.
				SharedPreferences.Editor mEditor = prefs.edit();
				mEditor.putBoolean(
						"com.therandoms.rtgdroid.enable_bad_filtering",
						enableBadWordsFiltering);
				mEditor.commit();

				String wordnikAPIKey = prefs.getString(
						"com.therandoms.rtgdroid.wordnik_api_key", null);
				int numResults = Integer.parseInt(prefs.getString("com.therandoms.rtgdroid.num_items_to_pull", "3"));
				// load the array of options.
				optionsToLoad.clear();
				for (int i = 0; i < adapter.getCount(); i++) {
					Pair<String> mPair = adapter.getItem(i);
					WordnikOptions newOption = new WordnikOptions(grammar,
							WordnikSortOrder.ASC, WordnikSortBy.ALPHA);
					newOption.grammarCategoryToLoad = mPair.item1;
					newOption.wordnikCategoriesToInclude
							.add(nonprintableCategories.get(printableCategories
									.indexOf(mPair.item2)));
					newOption.enableBadWordsFiltering = enableBadWordsFiltering;
					newOption.wordnikAPIKey = wordnikAPIKey;
					newOption.numResultsDesired = numResults;
					optionsToLoad.add(newOption);
				}
			}
		}
		adapter.clear();
		WordnikLoadingStep.super.onExit(exitCode);

	}

	/**
	 * A simple class for storing a pair of like-typed items.
	 * 
	 * @author Logan Widick
	 *
	 * @param <T>
	 *            The type of the item to store a pair of.
	 */
	public class Pair<T> {
		public T item1;
		public T item2;
	}

	/**
	 * An {@link ArrayAdapter} for {@link Pair} objects.
	 * 
	 * @author Logan Widick
	 *
	 * @param <T>
	 *            The type of the pairs.
	 */
	public class PairAdapter<T> extends ArrayAdapter<Pair<T>> {

		/**
		 * Constructor
		 * 
		 * @param context
		 *            the context
		 */
		public PairAdapter(Context context) {
			super(context, android.R.layout.simple_list_item_2);

		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View row = convertView;

			// create view if it does not exist
			if (row == null) {
				LayoutInflater inflater = (LayoutInflater) getActivity()
						.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				row = inflater.inflate(android.R.layout.simple_list_item_2,
						parent, false);
			}

			// load the items into the view
			Pair<T> item = getItem(position);
			TextView v = (TextView) row.findViewById(android.R.id.text1);
			v.setText(item.item1.toString());
			v = (TextView) row.findViewById(android.R.id.text2);
			v.setText(item.item2.toString());

			// return the view
			return row;
		}
	}

	/**
	 * The adapter to use for the drag sort list view
	 */
	private PairAdapter<String> adapter = null;

	/**
	 * The drop listener for the drag sort list view
	 */
	private DragSortListView.DropListener onDrop = new DragSortListView.DropListener() {
		@Override
		public void drop(int from, int to) {
			if (from != to) {
				Pair<String> item = adapter.getItem(from);
				adapter.remove(item);
				adapter.insert(item, to);
			}
		}
	};

	/**
	 * The remove listener for the drag sort list view
	 */
	private DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener() {
		@Override
		public void remove(int which) {
			// TODO Auto-generated method stub
			adapter.remove(adapter.getItem(which));
		}
	};

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// false is really important here. The program will crash without it.
		View v = inflater.inflate(R.layout.step_load_wordnik, container, false);

		// get references to UI components
		wordnikCategoriesSpinner = (Spinner) v
				.findViewById(R.id.wordnikGrammarCategorySpinner);
		productionCategoriesSpinner = (Spinner) v
				.findViewById(R.id.wordnikProductionCategorySpinner);
		selectedItemsListView = (DragSortListView) v
				.findViewById(R.id.wordnikDragSortView);

		// Set the adapter for the DSLV
		adapter = new PairAdapter<String>(getActivity());
		selectedItemsListView.setAdapter(adapter);

		// Set the listeners for the DSLV
		selectedItemsListView.setDropListener(onDrop);
		selectedItemsListView.setRemoveListener(onRemove);

		// Add a controller to the DSLV
		DragSortController controller = new DragSortController(
				selectedItemsListView);
		controller.setRemoveEnabled(true);
		controller.setSortEnabled(true);
		controller.setDragInitMode(1);
		selectedItemsListView.setFloatViewManager(controller);
		selectedItemsListView.setOnTouchListener(controller);
		selectedItemsListView.setDragEnabled(true);

		// set adapter for grammar production categories.
		productionCategoriesSpinner.setAdapter(new ArrayAdapter<String>(
				getActivity(), android.R.layout.simple_spinner_item,
				new ArrayList<String>(grammar.getProductionCategories())));

		// get reference to categories arrays
		nonprintableCategories = new ArrayList<String>(
				Arrays.asList(getResources().getStringArray(
						R.array.wordnik_categories_nonprintable)));
		printableCategories = new ArrayList<String>(
				Arrays.asList(getResources().getStringArray(
						R.array.wordnik_categories_printable)));

		// set on click event
		Button b = (Button) v.findViewById(R.id.wordnikAddButton);
		b.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// Add the pair from the spinners to the adapter.
				Pair<String> mPair = new Pair<String>();
				mPair.item1 = productionCategoriesSpinner.getSelectedItem()
						.toString();
				mPair.item2 = wordnikCategoriesSpinner.getSelectedItem()
						.toString();
				adapter.add(mPair);
			}
		});

		return v;
	}

}
